using System;
using System.Collections.Generic;
using SCG.SolarVengeanceEngine;
using SCG.SolarVengeanceEngine.StarShips;
using SCG.General;

namespace SCG.SolarVengeance.Scenarios
{
    public class ConvoyEscort : Scenario
    {
        #region Initializations

        private ScenarioParameter enbBH;
        private ScenarioParameter enbPL;
        private ScenarioParameter enbWH;
        private List<StarShip> vShip = new List<StarShip>();
        private Dictionary<Player, int> oShip = new Dictionary<Player, int>();
        private List<Wormhole> vWormHole = new List<Wormhole>();
        private List<BlackHole> vBlackHole = new List<BlackHole>();
        private List<Pulsar> vPulsar = new List<Pulsar>();
        private Dictionary<SCGPoint, bool> vPoint = new Dictionary<SCGPoint, bool>();
        private Random doublernd = new Random();
        

        public ConvoyEscort()
        {

            enbBH = CreateParameter("Black Holes Enabled?", 0, 0, 1);
            enbPL = CreateParameter("Pulsars Enabled?", 1, 0, 1);
            enbWH = CreateParameter("Worm Holes Enabled?", 1, 0, 1);

        }

        public override string Description
        {
            get
            {
                return "This is built as two-player scenario, but can support up to 4 players on teams.  Team 1 will take on the task of defending a " +
                       "convoy of freighters trying to deliver a vital shipment being delivered to the " +
                       "besiged starsystem of Kratula.  Team 2 will take on the role of the blockading " +
                       "starfleet.  Team 1 wins if Kratula is delivered 2000 resources.  Team 2 wins if " +
                       "enough freighters are destroyed to prevent Kratula from receiving 2000 resources.";
            }
        }
        public override bool UsesCapitals
        {
            get
            {
                return false;
            }
        }
        public override PlayModeRecommendation Recommendation
        {
            get
            {
                return PlayModeRecommendation.MultiPlayer;
            }
        }
        public override string Author
        {
            get
            {
                return "Ugly Green Things";
            }
        }
        public override int MapWidth
        {
            get
            {
                return 200;
            }
        }

        //don't assign capitals
        public override bool AssignCapitals
        {
            get
            {
                return false;
            }
        }

        public override int MaxPlayers
        {
            get
            {
                return 4;
            }
        }

        #endregion

        public override void BuildScenario(int numPlayers, int capitalValues, int startingResources)
        {
            #region Scenario Initializations

            //clear previously assigned dictionaries
            vShip.Clear();
            oShip.Clear();
            StarSystem kratula = null;

            //Determine fleet values for each player, they all share equal strengths
            int commandRange = Random(8, 13);
            int scanRange = Random(9, 15);
            int bs = Random(30, 50);
            int stRange = Random(8, 13);
            int spyRange = Random(5, 9);
            int players = 0;
            StarShip freight =  null;

            #endregion

                #region Create StarFleets

                foreach (Player p in Game.Players)
                {
                    players++;
                }

                for (int buildTurn = 0; buildTurn < players; buildTurn++)
                {

                //if (buildTurn == 0)
                if (buildTurn % 2 == 0)
                {
                    Player p = Game.Players[buildTurn];
                    oShip[p] = 0;

                    //center Battlestation at this location
                    int x = 180;
                    int y = 50 + (buildTurn * 10);
                    CreateStarShip(x, y, p, StarShipType.BattleStation, 6, bs, false);

                    //create scanship
                    CreateStarShip(x - 4, y, p, StarShipType.ScanShip, 20, scanRange, false);

                    //create Drones
                    for (int d = 0; d < 5; d++)
                    {
                        CreateStarShip(x + 2 + d, y + 2, p, StarShipType.Drone, 12, 0, false);
                        CreateStarShip(x + 2 + d, y - 2, p, StarShipType.Drone, 12, 0, false);
                    }

                    //create W3 scouts
                    for (int scout = 0; scout < 8; scout++)
                        CreateStarShip(x - 6, y - 4 + scout, p, StarShipType.WarShip, 14, 3, false);

                    //create W4 battery
                    for (int w4 = 0; w4 < 6; w4++)
                    {
                        CreateStarShip(x - 5, y - 3 + w4, p, StarShipType.WarShip, 12, 4, false);
                    }

                    //create W6 battery & Elites
                    for (int w6 = 0; w6 < 2; w6++)
                    {
                        CreateStarShip(x + 4 + w6, y - 4, p, StarShipType.WarShip, 10, 6, false);
                        CreateStarShip(x + 4 + w6, y + 4, p, StarShipType.Elite, 20, 5, false);
                    }


                    //create SpyShip
                    CreateStarShip(x - 2, y, p, StarShipType.SpyShip, 15, spyRange, false);

                    //create CommandShip
                    CreateStarShip(x - 3, y + 1, p, StarShipType.CommandShip, 20, commandRange, false);

                    //create StarTillery
                    CreateStarShip(x, y - 2, p, StarShipType.StarTillery, 20, stRange, false);
                    CreateStarShip(x, y + 2, p, StarShipType.StarTillery, 20, stRange, false);

                    //create cloaked groups
                    for (int c = 0; c < 2; c++)
                    {
                        CreateStarShip(x + c, y - 4, p, StarShipType.WarShip, 15, 7, true);
                        CreateStarShip(x + c, y + 4, p, StarShipType.WarShip, 15, 7, true);
                    }

                    //create Freighters
                    for (int f = 0; f < 10; f++)
                    {
                        freight = CreateStarShip(x + 2 + f, y, p, StarShipType.Freighter, 6, 100, false);
                        Freighter fr = freight as Freighter;
                        fr.Resources = 1000;
                    }
                }
                else
                {
                    Player p = Game.Players[buildTurn];
                    oShip[p] = 0;
                    int j = 0;

                    for (int i = 0; i < 2; i++)
                    {
                        
                        //center Battlestation at this location
                        int x = 30;
                        int y = 80 - (buildTurn * 10) + j - (buildTurn * 10);
                        CreateStarShip(x, y, p, StarShipType.BattleStation, 6, bs, false);

                        //create scanship
                        CreateStarShip(x + 4, y, p, StarShipType.ScanShip, 20, scanRange, false);

                        //create Drones
                        for (int d = 0; d < 5; d++)
                        {
                            CreateStarShip(x - 2 - d, y + 2, p, StarShipType.Drone, 12, 0, false);
                            CreateStarShip(x - 2 - d, y - 2, p, StarShipType.Drone, 12, 0, false);
                        }

                        //create W3 scouts
                        for (int scout = 0; scout < 8; scout++)
                            CreateStarShip(x + 6, y - 4 + scout, p, StarShipType.WarShip, 14, 3, false);

                        //create W4 battery
                        for (int w4 = 0; w4 < 6; w4++)
                        {
                            CreateStarShip(x + 5, y - 3 + w4, p, StarShipType.WarShip, 12, 4, false);
                        }

                        //create W6 battery & Elites
                        for (int w6 = 0; w6 < 2; w6++)
                        {
                            CreateStarShip(x - 4 - w6, y - 4, p, StarShipType.WarShip, 10, 6, false);
                            CreateStarShip(x - 4 - w6, y + 4, p, StarShipType.Elite, 20, 5, false);
                        }


                        //create SpyShip
                        CreateStarShip(x + 2, y, p, StarShipType.SpyShip, 15, spyRange, false);

                        //create CommandShip
                        CreateStarShip(x + 3, y + 1, p, StarShipType.CommandShip, 20, commandRange, false);

                        //create StarTillery
                        CreateStarShip(x, y - 2, p, StarShipType.StarTillery, 20, stRange, false);
                        CreateStarShip(x, y + 2, p, StarShipType.StarTillery, 20, stRange, false);

                        //create cloaked groups
                        for (int c = 0; c < 2; c++)
                        {
                            CreateStarShip(x - c, y - 4, p, StarShipType.WarShip, 15, 7, true);
                            CreateStarShip(x - c, y + 4, p, StarShipType.WarShip, 15, 7, true);
                        }

                        //create Freighters
                        for (int f = 0; f < 3; f++)
                        {
                            freight = CreateStarShip(x - 2 - f, y, p, StarShipType.Freighter, 6, 100, false);
                            Freighter fr = freight as Freighter;
                            fr.Resources = 1000;
                        }

                        j = j + 20;
                    }
                    
                }
            }
                #endregion

            #region Create Map

            //Create Player 2 Starsystem
            
            kratula = CreateStarSystem(Random(5, 15), Random(45, 55), 0, 300, 10, 0);
            kratula.Owner = Game.Players[0];
            kratula.Name = "Kratula";

            //Create Random Nebula
            int numNebula = SVGame.RNG.Next(4) + 2;
            while (numNebula > 0)
            {
                CreateNebula(SVGame.RNG.Next(80) + 60, SVGame.RNG.Next(40) + 30, SVGame.RNG.Next(5) + 4, SVGame.RNG.Next(40) + 30);
                numNebula--;
            }
            //Create Random Wormholes
            int numWormholes = SVGame.RNG.Next(4) + 1;
            while (numWormholes > 0 && enbWH.Value == 1)
            {
                CreateWormhole(SVGame.RNG.Next(200), SVGame.RNG.Next(100), SVGame.RNG.Next(40) + 30, SVGame.RNG.Next(40) + 30);
                numWormholes--;
            }
            numWormholes = SVGame.RNG.Next(4) + 1;
            while (numWormholes > 0 && enbWH.Value == 1)
            {
                CreateWormhole(SVGame.RNG.Next(80) + 60, SVGame.RNG.Next(40) + 30, SVGame.RNG.Next(100), SVGame.RNG.Next(100));
                numWormholes--;
            }
            //Create Random Pulsars within the cluster
            int pulsars = Random(numPlayers, (numPlayers + 3));
            while (pulsars > 0 && enbPL.Value == 1)
            {
                SCGPoint ptPulsar = new SCGPoint();
                ptPulsar = new SCGPoint(Random(25, 175), Random(25, 75));
                CreatePulsar((int)ptPulsar.X, (int)ptPulsar.Y);
                pulsars--;
            }

            //Create Black Holes just outside the cluster perimeter
            int BlackHolesCreated = 0;
            Dictionary<int, int> BHInfoXpos = new Dictionary<int, int>();
            Dictionary<int, int> BHInfoYpos = new Dictionary<int, int>();
            int bhX = 0;
            int bhY = 0;
            int BlackHoles = Random(numPlayers, (numPlayers + 10));
            while (BlackHoles > 0 && enbBH.Value == 1)
            {
                bool BlackHolesOK = false;
                SCGPoint ptBlackHoles = new SCGPoint();
                do
                {
                    ptBlackHoles = new SCGPoint(Random(10, 190), Random(10, 90));
                    double dist = Distance(ptBlackHoles.X, ptBlackHoles.Y, 50, 50);
                    BlackHolesOK = dist > 45;
                    if (BlackHolesOK == true)
                    {
                        if (BlackHolesCreated > 0)
                        {
                            for (int d = 0; d < BlackHolesCreated; d++)
                            {
                                bhX = BHInfoXpos[d];
                                bhY = BHInfoYpos[d];
                                double bhdist = Distance(ptBlackHoles.X, ptBlackHoles.Y, bhX, bhY);
                                if (bhdist < 10)
                                    BlackHolesOK = false;
                            }
                        }
                    }
                }
                while (!BlackHolesOK);
                CreateBlackHole((int)ptBlackHoles.X, (int)ptBlackHoles.Y, Random(10, 15));
                BHInfoXpos.Add(BlackHolesCreated, (int)ptBlackHoles.X);
                BHInfoYpos.Add(BlackHolesCreated, (int)ptBlackHoles.Y);
                BlackHolesCreated++;
                BlackHoles--;
            }

            #endregion

        }

        #region Process Player Information and Victory Conditions

        public override void ProcessImpulse(int impulse)
        {
            StarSystem kratula = Game.StarSystems[0];

            if (impulse == 1)
            {
                DynamicEvents.DisplayMessage("Player 1 must deliver at least 2000 resources to Kratula.");
            }

            #region Count Freighters for Player 1
            else
            {
                for (int vcTurn = 0; vcTurn < 2; vcTurn++)
                {

                    if (vcTurn == 0)
                    {
                        Player p = Game.Players[0];
                        oShip[p] = 0;
                        foreach (StarShip s in Game.StarShips)
                        {
                            if (s.Owner == p)
                            {
                                if (s.ShipType == StarShipType.Freighter)
                                {
                                    oShip[p]++;
                                }
                            }
                        }
                        if (oShip[p] < 2)
                            p.Eliminated = true;
                    }
                    if (vcTurn == 1)
                    {
                        Player q = Game.Players[1];
                        if (kratula.Resources >= 2000)
                            q.Eliminated = true;
                    }
                }
            }
            #endregion

        }

        #endregion
    }
}
